use chrono::Local;
use sqlx::{PgPool, Error};
use struct_field_names_as_array::FieldNamesAsSlice;

use crate::core::psqlx_tools::SqlString;
use crate::model::admin::AdminModel;
use crate::model::model::Model;
use crate::types::backend::admin_type::{AdminDetail, AdminForm, AdminRow};


pub struct AdminService;

impl AdminService {
    /// 获取所有管理员
    /// 正确返回 AdminRow 数组
    /// 错误返回 sqlx::Error
    pub async fn get_all_admins(db: &PgPool) -> Result<Vec<AdminRow>, Error> {
        let model = AdminModel::new();
        let sql = SqlString::new(model.table())
        .field_slice(AdminRow::FIELD_NAMES_AS_SLICE)
        .order_primary_key_desc()
        .select();

        let res = sqlx::query_as::<_, AdminRow>(&sql)
        .fetch_all(db)
        .await;
        
        res
    }

    /// 获取管理员详情
    /// 参数 id 管理员id
    /// 正确返回 AdminForm 表单数据
    /// 错误返回 sqlx::Error
    pub async fn get_admin_by_id(db: &PgPool, id: i64) -> Result<AdminDetail, Error> {
        let model = AdminModel::new();
        let sql = SqlString::new(model.table())
        .field_slice(AdminDetail::FIELD_NAMES_AS_SLICE)
        .where_primary_key()
        .select();

        let res = sqlx::query_as::<_, AdminDetail>(&sql)
        .bind(id)
        .fetch_one(db)
        .await;

        res
    }

    /// 添加管理员
    /// 参数 data AdminForm 表单数据
    /// 正确返回 bool true
    /// 错误返回 sqlx::Error
    pub async fn insert_admin(db: &PgPool, data: &AdminForm) -> Result<bool, Error> {
        let model = AdminModel::new();
        let sql = SqlString::new(model.table())
        .field_slice(AdminForm::FIELD_NAMES_AS_SLICE)
        .insert();

        let res = sqlx::query(&sql)
        .bind(&data.name)
        .bind(&data.password)
        .execute(db)
        .await;

        match res {
            Ok(data) => Ok(data.rows_affected() > 0),
            Err(e) => Err(e)
        }
    }

    /// 更新管理员
    /// 参数 data AdminForm 表单数据
    /// 正确返回 bool true
    /// 错误返回 sqlx::Error
    pub async fn update_admin(db: &PgPool, id:i64, data: &AdminForm) -> Result<bool, Error> {
        let model = AdminModel::new();
        let sql = SqlString::new(model.table())
        .field_slice(AdminForm::FIELD_NAMES_AS_SLICE)
        .where_primary_key()
        .update();

        let res = sqlx::query(&sql)
        .bind(id)
        .bind(&data.name)
        .bind(&data.password)
        .execute(db)
        .await;

        match res {
            Ok(data) => Ok(data.rows_affected() > 0),
            Err(e) => Err(e)
        }
    }

    /// 删除管理员
    /// 参数 id 管理员id
    /// 正确返回 bool true
    /// 错误返回 sqlx::Error
    pub async fn delete_admin(db: &PgPool, id: i64) -> Result<bool, Error> {
        let model = AdminModel::new();
        let sql = SqlString::new(model.table())
        .where_primary_key()
        .delete();

        let res = sqlx::query(&sql)
        .bind(id)
        .execute(db)
        .await;

        match res {
            Ok(data) => Ok(data.rows_affected() > 0),
            Err(e) => Err(e)
        }
    }

    /// 管理员是否存在
    /// 参数 id 管理员id
    /// 正确返回 数量
    /// 错误返回 sqlx::Error
    pub async fn exist_admin_by_id(db: &PgPool, id: i64) -> Result<i64, Error> {
        let model = AdminModel::new();
        let sql = SqlString::new(model.table())
        .where_primary_key()
        .count();

        let res = sqlx::query_scalar::<_, i64>(&sql)
        .bind(id)
        .fetch_one(db)
        .await;

        res
    }

    /// 根据名称获取管理员详情
    /// 参数 name 管理员用户名
    /// 正确返回 AdminForm 表单数据
    /// 错误返回 sqlx::Error
    pub async fn get_admin_by_name(db: &PgPool, name: &str) -> Result<AdminDetail, Error> {
        let model = AdminModel::new();
        let sql = SqlString::new(model.table())
        .field_slice(AdminDetail::FIELD_NAMES_AS_SLICE)
        .where_eq(model.name())
        .select();

        let res = sqlx::query_as::<_, AdminDetail>(&sql)
        .bind(name)
        .fetch_one(db)
        .await;

        res
    }

    /// 更新管理员登录记录
    /// 正确返回 bool true
    /// 错误返回 sqlx::Error
    pub async fn update_admin_login(db: &PgPool, id:i64, count: i64) -> Result<bool, Error> {
        let model = AdminModel::new();
        let sql = SqlString::new(model.table())
        .field("login_count,last_login")
        .where_primary_key()
        .update();

        let res = sqlx::query(&sql)
        .bind(id)
        .bind(count)
        .bind(Local::now())
        .execute(db)
        .await;

        match res {
            Ok(data) => Ok(data.rows_affected() > 0),
            Err(e) => Err(e)
        }
    }
}
    